﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.InteropServices;
using System.Web.Security;

/// <summary>
/// Classe com rotinas de Login
/// </summary>
public class LoginDominio
{
    [DllImport("ADVAPI32.dll", EntryPoint = "LogonUserW", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

	public LoginDominio()
	{
		//
		// TODO: Add constructor logic here
		//
	}
    /// <summary>Analisa a string para retirar o nome do domínio do dominio.</summary>
    /// <param name="usernameDomain">The string to parse that must contain 
    /// the domain in either the domain\username or UPN format username@domain</param>
    /// <returns>O nome do dominio ou "" se não existir</returns>
    public static string GetDomainName(string usernameDomain)
    {
        if (string.IsNullOrEmpty(usernameDomain))
        {
            throw (new ArgumentException("Argument can’t be null.", "usernameDomain"));
        }
        if (usernameDomain.Contains("\\"))
        {
            int index = usernameDomain.IndexOf("\\");
            return usernameDomain.Substring(0, index);
        }
        else if (usernameDomain.Contains("@"))
        {
            int index = usernameDomain.IndexOf("@");
            return usernameDomain.Substring(index + 1);
        }
        else
        {
            return "";
        }
        
    }
    /// <summary>Analisa a string para retirar o nome de usuário do dominio</summary>
    /// <param name="usernameDomain">Para analisar a string deve conter o username 
    /// tanto como dominio/usuario ou UPN username@domain</param>
    /// <returns>O nome de usuário ou a vazio, se não for encontrado um domínio.</returns>
    public static string GetUsername(string usernameDomain)
    {
        if (string.IsNullOrEmpty(usernameDomain))
        {
            throw (new ArgumentException("Argument can’t be null.", "usernameDomain"));
        }
        if (usernameDomain.Contains("\\"))
        {
            int index = usernameDomain.IndexOf("\\");
            return usernameDomain.Substring(index + 1);
        }
        else if (usernameDomain.Contains("@"))
        {
            int index = usernameDomain.IndexOf("@");
            return usernameDomain.Substring(0, index);
        }
        else
        {
            return usernameDomain;
        }
    }
    /// <summary>Analisa o usuário e senha passados como parametro, para que possa logar no dominio</summary>
    /// <param name="usuario">Nome de usuario que esta para se logar</param>
    /// <param name="senha">Senha do Usuário que esta para se logar</param>
    /// <param name="continuarlogado">Verdadeiro para criar um cookie, falso para criar uma sessão</param>
    /// <returns>Um valor boleano, verdadeiro para logado com sucesso, e falso quando ocorrer algum erro</returns>
    public bool LogarUsuario(string usuario, string senha, bool continuarlogado)
    {
        string domainName = GetDomainName(usuario);
        string userName = GetUsername(usuario);
        IntPtr token = IntPtr.Zero;
        /*
         * userName, domainName and Password parameters are very obvious.
         */
        /*
         * Eu uso LOGON32_LOGON_INTERACTIVE, este tipo de logon é destinado a usuários que serão 
         * interativamente usando o computador, como sendo um usuário conectado por um servidor de 
         * terminal, shell remoto, ou processo similar. Este tipo de logon tem a despesa adicional 
         * de informações de cache de logon para as operações desconectadas. Para mais detalhes sobre 
         * esse parâmetro, consulte http://msdn.microsoft.com/en-us/library/aa378184(VS.85).aspx
         */
        /* 
         * DwLogonProvider (parâmetro 4): Eu usei LOGON32_PROVIDER_DEFAUL, Este provedor
         * usa o provedor de logon padrão para o sistema. O provedor de segurança padrão é
         * negociar, a menos que você passar NULL para o nome de domínio eo nome do usuário não estiver na UPN
         * formato. Neste caso, o provedor padrão é o NTLM. Para mais detalhes sobre este
         * parâmetro consulte http://msdn.microsoft.com/en-us/library/aa378184(VS.85).aspx 
         */

        /* 
         * PhToken (parâmetro 5): Um ponteiro para um identificador variável que recebe um identificador para
         * um símbolo que representa o usuário especificado. Podemos usar o manipulador de representação efeito. 
         */
        bool result = LogonUser(userName, domainName, senha, 2, 0, ref token);
        if (result)
        {
            // Se for autenticado com êxito
            /* 
             * Quando um usuário unatuthenticated tentar visitar qualquer página do seu aplicativo que está
             * permitido somente a visualização por usuários autenticados, em seguida, o ASP.NET automaticamente redirecionar essa
             * usuário para formulários de login e adicione ReturnUrl parâmetro de seqüência de consulta que contém a URL de um
             * página que o usuário quer visitar, de modo que podemos redirecionar o usuário para a página depois
             * autenticado. FormsAuthentication.RedirectFromLoginPage () método não só redirecionar
             * o usuário para a página, mas também genrate um token de autenticação para o usuário. 
             */

            if (string.IsNullOrEmpty(HttpContext.Current.Request.QueryString["ReturnUrl"]))
            {
                FormsAuthentication.RedirectFromLoginPage(usuario, continuarlogado);
            }
            /* 
             * Se ReturnUrl parâmetro de seqüência de consulta não está presente, então temos de gerar
             * token de autenticação e redirecionar o usuário para uma página (de acordo com sua aplicação
             * necessidade). FormsAuthentication.SetAuthCookie método () irá gerar a autenticação Token 
            */
            else
            {
                FormsAuthentication.SetAuthCookie(usuario, continuarlogado);
            }
            return true;
        }
        else
        {
            //Usuário não autenticado
            return false;
        }
    }

}